#pragma once
#include "VIEU_OP_enum.h"
#include "../../instruction_module/instruction.h"
#include"../../execution_module/write_delay_control/write_delay_control.h"
#include <iostream>
#include "../../System_config.h"
#include"../../instruction_module/operands.h"

#define MASK_SIGN_ADD 0x8000000000000000
#define MASK_SIGN_SUB 0xC000000000000000
#define MASK_UNSIGN_ADD 0x0000000000000000
#define MASK_UNSIGN_SUB 0x4000000000000000
#define MASK_SIGN_UP_OVERFLOW 0x1000000000000000
#define MASK_SIGN_UNDER_OVERFLOW 0x2000000000000000
#define MASK_SIGN_UP_OVERFLOW_LOW 0x0400000000000000
#define MASK_SIGN_UNDER_OVERFLOW_LOW 0x0800000000000000
//无符号加减法，只置位C1即可，MSB1无需考虑，因此统一置为0
#define MASK_UNSIGN_UP_OVERFLOW 0x2000000000000000
#define MASK_UNSIGN_UP_OVERFLOW_LOW 0x0800000000000000
#define MASK_SATa0 0x0000000000000001
#define MASK_SATa1 0x0000000000000002

//TODO:跟路哥确认一下inline double do_VIEU的具体执行逻辑，以及inline double do_VIEU对应的汇编指令
class VIEU {
public:
    VIEU(int vieu_id) :  id(vieu_id){}
    VIEU(std::vector<base_operand*>* operands, int vieu_id) 
                : operand_list(operands), id(vieu_id){
        delay_cycles = 1;
    }
    VIEU(int vieu_id, RegisterFile* rf) : id(vieu_id), RF(rf) {
        delay_cycles = 1;
    }
    ~VIEU() {}
    int get_delay();
    void input_operands(std::vector<base_operand*>* operands);
    uint64_t Execute(instruction* vieu_instr);
    write_req_info_reg  upload_write_msg();
    inline uint64_t read_Reg(int reg_id);
    inline void write_Reg(int reg_id, uint64_t value, int delay);
    inline uint64_t do_VADD_src1_vr(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 111_0000_100; execution cycle = 1
    inline uint64_t do_VADD_src1_imm(uint64_t imm, int src2_reg_id, int dst_reg_id); //op = 111_1000_100; execution cycle = 1
    inline uint64_t do_VADDU_src1_vr(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 110_0000_100; execution cycle = 1
    inline uint64_t do_VADDU_src1_imm(uint64_t imm, int src2_reg_id, int dst_reg_id); //op = 110_1000_100; execution cycle = 1
    inline uint64_t do_VADD32_src1_vr(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 101_0000_100; execution cycle = 1
    inline uint64_t do_VADD32_src1_imm(uint64_t imm, int src2_reg_id, int dst_reg_id); //op = 101_1000_100; execution cycle = 1
    inline uint64_t do_VADDU32_src1_vr(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 100_0000_100; execution cycle = 1
    inline uint64_t do_VADDU32_src1_imm(uint64_t imm, int src2_reg_id, int dst_reg_id); //op = 100_1000_100; execution cycle = 1
    inline uint64_t do_VSUB_src1_vr(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 111_0000_000; execution cycle = 1
    inline uint64_t do_VSUB_src1_imm(uint64_t imm, int src2_reg_id, int dst_reg_id); //op = 111_1000_000; execution cycle = 1
    inline uint64_t do_VSUBU_src1_vr(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 110_0000_000; execution cycle = 1
    inline uint64_t do_VSUBU_src1_imm(uint64_t imm, int src2_reg_id, int dst_reg_id); //op = 110_1000_000; execution cycle = 1
    inline uint64_t do_VSUBC(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 110_0000_010; execution cycle = 1
    inline uint64_t do_VSUB32_src1_vr(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 101_0000_000; execution cycle = 1
    inline uint64_t do_VSUB32_src1_imm(uint64_t imm, int src2_reg_id, int dst_reg_id); //op = 101_1000_000; execution cycle = 1
    inline uint64_t do_VSUBU32_src1_vr(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 100_0000_000; execution cycle = 1
    inline uint64_t do_VSUBU32_src1_imm(uint64_t imm, int src2_reg_id, int dst_reg_id); //op = 100_1000_000; execution cycle = 1
    inline uint64_t do_VSUBC32(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 100_0000_010; execution cycle = 1
    inline uint64_t do_VSAT(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 111_0101_000; execution cycle = 1
    inline uint64_t do_VSAT32(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 101_0101_000; execution cycle = 1
    inline uint64_t do_VNEG(int src2_reg_id, int dst_reg_id); //op = 111_0100_100; execution cycle = 1
    inline uint64_t do_VNEG32(int src2_reg_id, int dst_reg_id); //op = 101_0100_100; execution cycle = 1
    inline uint64_t do_VABS(int src2_reg_id, int dst_reg_id); //op = 111_0100_000; execution cycle = 1
    inline uint64_t do_VABS32(int src2_reg_id, int dst_reg_id); //op = 101_0100_000; execution cycle = 1
    inline uint64_t do_VMAX(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 111_0001_100; execution cycle = 1
    inline uint64_t do_VMAXU(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 110_0001_100; execution cycle = 1
    inline uint64_t do_VMAX32(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 101_0001_100; execution cycle = 1
    inline uint64_t do_VMAXU32(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 100_0001_100; execution cycle = 1
    inline uint64_t do_VMIN(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 111_0001_000; execution cycle = 1
    inline uint64_t do_VMINU(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 110_0001_000; execution cycle = 1
    inline uint64_t do_VMIN32(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 101_0001_000; execution cycle = 1
    inline uint64_t do_VMINU32(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 100_0001_000; execution cycle = 1
    inline uint64_t do_VEQ_src1_vr(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 111_0010_000; execution cycle = 1
    inline uint64_t do_VEQ_src1_imm(uint64_t imm, int src2_reg_id, int dst_reg_id); //op = 111_1010_000; execution cycle = 1
    inline uint64_t do_VLT_src1_vr(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 111_0010_010; execution cycle = 1
    inline uint64_t do_VLT_src1_imm(uint64_t imm, int src2_reg_id, int dst_reg_id); //op = 111_1010_010; execution cycle = 1
    inline uint64_t do_VLTU_src1_vr(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 110_0010_010; execution cycle = 1
    inline uint64_t do_VLTU_src1_imm(uint64_t imm, int src2_reg_id, int dst_reg_id); //op = 110_1010_010; execution cycle = 1
    inline uint64_t do_VEQ32_src1_vr(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 101_0010_000; execution cycle = 1
    inline uint64_t do_VEQ32_src1_imm(uint64_t imm, int src2_reg_id, int dst_reg_id); //op = 101_1010_000; execution cycle = 1
    inline uint64_t do_VLT32_src1_vr(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 101_0010_010; execution cycle = 1
    inline uint64_t do_VLT32_src1_imm(uint64_t imm, int src2_reg_id, int dst_reg_id); //op = 101_1010_010; execution cycle = 1
    inline uint64_t do_VLTU32_src1_vr(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 100_0010_010; execution cycle = 1
    inline uint64_t do_VLTU32_src1_imm(uint64_t imm, int src2_reg_id, int dst_reg_id); //op = 100_1010_010; execution cycle = 1
    inline uint64_t do_VMOV_VIEU(int src2_reg_id, int dst_reg_id); //op = 111_1110_001; execution cycle = 1
    inline uint64_t do_VMVCGC(int src2_reg_id, int dst_reg_id); //op = 111_1110_010; execution cycle = 1/2
    inline uint64_t do_VMVCCG(int src2_reg_id, int dst_reg_id); //op = 111_1110_011; execution cycle = 1/2
    inline uint64_t do_VMOVI_VIEU(uint64_t imm, int dst_reg_id); //op 80位指令; execution cycle = 1
    inline uint64_t do_VMOVI24_VIEU(uint64_t imm, int dst_reg_id); //op 40位指令; execution cycle = 1
    inline uint64_t do_VAND_src1_vr(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 111_0011_000; execution cycle = 1
    inline uint64_t do_VAND_src1_imm(uint64_t imm, int src2_reg_id, int dst_reg_id); //op = 111_1011_000; execution cycle = 1
    inline uint64_t do_VOR_src1_vr(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 111_0011_010; execution cycle = 1
    inline uint64_t do_VOR_src1_imm(uint64_t imm, int src2_reg_id, int dst_reg_id); //op = 111_1011_010; execution cycle = 1
    inline uint64_t do_VXOR_src1_vr(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 111_0011_100; execution cycle = 1
    inline uint64_t do_VXOR_src1_imm(uint64_t imm, int src2_reg_id, int dst_reg_id); //op = 111_1011_100; execution cycle = 1
    inline uint64_t do_VNOT_src1_vr(int src2_reg_id, int dst_reg_id); //op = 111_0011_110; execution cycle = 1
    inline uint64_t do_VNOT_src1_imm(uint64_t imm, int dst_reg_id); //op = 111_1011_110; execution cycle = 1
    inline uint64_t do_VLZD(int src2_reg_id, int dst_reg_id); //op = 111_0101_100; execution cycle = 1
    inline uint64_t do_VLZD32(int src2_reg_id, int dst_reg_id); //op = 101_0101_100; execution cycle = 1
    inline uint64_t do_VSHFLL32_src1_vr(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 0000_0000_00; execution cycle = 1
    inline uint64_t do_VSHFLL32_src1_imm(uint64_t imm, int src2_reg_id, int dst_reg_id); //op = 0010_0000_00; execution cycle = 1
    inline uint64_t do_VSHFLL_src1_vr(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 0100_0000_00; execution cycle = 1
    inline uint64_t do_VSHFLL_src1_imm(uint64_t imm, int src2_reg_id, int dst_reg_id); //op = 0110_0000_00; execution cycle = 1
    inline uint64_t do_VSHFLR32_src1_vr(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 0000_1000_00; execution cycle = 1
    inline uint64_t do_VSHFLR32_src1_imm(uint64_t imm, int src2_reg_id, int dst_reg_id); //op = 0010_1000_00; execution cycle = 1
    inline uint64_t do_VSHFLR_src1_vr(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 0100_1000_00; execution cycle = 1
    inline uint64_t do_VSHFLR_src1_imm(uint64_t imm, int src2_reg_id, int dst_reg_id); //op = 0110_1000_00; execution cycle = 1
    inline uint64_t do_VSHFAR32_src1_vr(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 0001_0000_00; execution cycle = 1
    inline uint64_t do_VSHFAR32_src1_imm(uint64_t imm, int src2_reg_id, int dst_reg_id); //op = 0011_0000_00; execution cycle = 1
    inline uint64_t do_VSHFAR_src1_vr(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 0101_0000_00; execution cycle = 1
    inline uint64_t do_VSHFAR_src1_imm(uint64_t imm, int src2_reg_id, int dst_reg_id); //op = 0111_0000_00; execution cycle = 1
    inline uint64_t do_VBCLR32(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 0000_0010_00; execution cycle = 1
    inline uint64_t do_VBCLR(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 0100_0010_00; execution cycle = 1
    inline uint64_t do_VBSET32(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 0000_1010_00; execution cycle = 1
    inline uint64_t do_VBSET(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 0100_1010_00; execution cycle = 1
    inline uint64_t do_VBEX32(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 0001_0010_00; execution cycle = 1
    inline uint64_t do_VBEX(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 0101_0010_00; execution cycle = 1
    inline uint64_t do_VBTST32(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 0001_1010_00; execution cycle = 1
    inline uint64_t do_VBTST(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 0101_1010_00; execution cycle = 1
    inline uint64_t do_VBEXT32(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 0010_0010_00; execution cycle = 1
    inline uint64_t do_VBEXT(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 0110_0010_00; execution cycle = 1
    inline uint64_t do_VBEXT32U(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 0010_1010_00; execution cycle = 1
    inline uint64_t do_VBEXTU(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 0110_1010_00; execution cycle = 1
    inline uint64_t do_VBALE2(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 0000_0100_00; execution cycle = 1
    inline uint64_t do_VBALE2H(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 0000_1100_00; execution cycle = 1
    inline uint64_t do_VBALE2LH(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 0001_0100_00; execution cycle = 1
    inline uint64_t do_VBALE2HL(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 0001_1100_00; execution cycle = 1
    inline uint64_t do_VBALE4H(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 0010_0100_00; execution cycle = 1
    inline uint64_t do_VBALE4L(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 0010_1100_00; execution cycle = 1
    inline uint64_t do_VSBALE2(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 0011_0100_00; execution cycle = 1
    inline uint64_t do_VSBALE4(int src1_reg_id, int src2_reg_id, int dst_reg_id); //op = 0011_1100_00; execution cycle = 1
    inline uint64_t do_VUBALE4H(int src2_reg_id, int dst_reg_id); //op = 0100_0100_00; execution cycle = 1
    inline uint64_t do_VUBALE4L(int src2_reg_id, int dst_reg_id); //op = 0100_1100_00; execution cycle = 1
    inline uint64_t do_VITL2(int src2_reg_id, int dst_reg_id); //op = 0101_0100_00; execution cycle = 1
    inline uint64_t do_VITL4(int src2_reg_id, int dst_reg_id); //op = 0101_1100_00; execution cycle = 1
private:
    int id;
    std::vector<base_operand*>* operand_list;
    uint64_t res_value;
    int dst_reg_id;
    int delay_cycles; //用于标记该硬件单元从接收到输入，直到给出输出的延迟周期，根据不同的指令类型，应有不同的延迟周期

    RegisterFile* RF;

    static inline float int16_to_float(int16_t v) {
        float f;
        std::memcpy(&f, &v, sizeof(f));
        return f;
    }

    float fp16_to_float(uint16_t fp16) {
    // 实现 fp16 到 float 的转换逻辑
    // 这里可以使用库函数或手动实现
    // 以下是一个简单的示例实现（假设 fp16 是 IEEE 754 半精度格式）
    uint32_t sign = (fp16 >> 15) & 0x1;
    uint32_t exponent = (fp16 >> 10) & 0x1F;
    uint32_t mantissa = fp16 & 0x3FF;

    if (exponent == 0) {
        // 零或非规格化数
        return (sign ? -0.0f : 0.0f);
    } else if (exponent == 0x1F) {
        // 无穷大或 NaN
        return (mantissa == 0) ? (sign ? -INFINITY : INFINITY) : NAN;
    } else {
        // 规格化数
        exponent -= 15; // 调整指数偏移
        mantissa |= 0x400; // 添加隐含的 1
        float value = std::ldexp(mantissa, exponent - 10);
        return sign ? -value : value;
    }
}


    uint16_t float_to_fp16(float value) {
    // 实现 float 到 fp16 的转换逻辑
    // 这里可以使用库函数或手动实现
    // 以下是一个简单的示例实现（假设 fp16 是 IEEE 754 半精度格式）
    uint32_t bits = *reinterpret_cast<uint32_t*>(&value);
    uint32_t sign = (bits >> 31) & 0x1;
    uint32_t exponent = (bits >> 23) & 0xFF;
    uint32_t mantissa = bits & 0x7FFFFF;

    if (exponent == 0xFF) {
        // 无穷大或 NaN
        return (sign << 15) | 0x7C00 | (mantissa ? 0x200 : 0);
    } else if (exponent == 0) {
        // 零或非规格化数
        return (sign << 15);
    } else {
        // 规格化数
        exponent -= 127; // 调整指数偏移
        if (exponent > 15) {
            // 溢出，返回无穷大
            return (sign << 15) | 0x7C00;
        } else if (exponent < -14) {
            // 非规格化数
            return (sign << 15);
        } else {
            // 规格化数
            exponent += 15; // 调整指数偏移
            mantissa >>= 13; // 截断尾数
            return (sign << 15) | (exponent << 10) | mantissa;
        }
    }
}

    static inline float uint32_to_float(uint32_t v) {
        float f;
        std::memcpy(&f, &v, sizeof(f));
        return f;
    }

    static inline float int32_to_float(int32_t v) {
        float f;
        std::memcpy(&f, &v, sizeof(f));
        return f;
    }

    static inline uint32_t float_to_uint32(float f) {
        uint32_t v;
        std::memcpy(&v, &f, sizeof(v));
        return v;
    }

    static inline int32_t float_to_int32(float f) {
        int32_t v;
        std::memcpy(&v, &f, sizeof(v));
        return v;
    }

    static inline float double_to_float(double v) {
        float f;
        std::memcpy(&f, &v, sizeof(f));
        return f;
    }

    static inline float float_to_double(float v) {
        double f;
        std::memcpy(&f, &v, sizeof(f));
        return f;
    }


    static inline double uint64_to_double(uint64_t v) {
        double f;
        std::memcpy(&f, &v, sizeof(f));
        return f;
    }

    static inline double int64_to_double(int64_t v) {
        double f;
        std::memcpy(&f, &v, sizeof(f));
        return f;
    }

    static inline int64_t double_to_int64(double v) {
        int64_t f;
        std::memcpy(&f, &v, sizeof(f));
        return f;
    }

    void extract_fp16_components(uint16_t fp16, bool &sign, uint8_t &exponent, uint16_t &mantissa) {
    sign = (fp16 >> 15) & 0x1; // 符号位
    exponent = (fp16 >> 10) & 0x1F; // 指数位
    mantissa = fp16 & 0x3FF; // 尾数位
    }

    // 将尾数转换为补码形式（带符号扩展）

    int16_t mantissa_to_complement(bool sign, uint16_t mantissa) {
        // 尾数占 10 位，加上隐藏位（如果指数不为 0），总共 11 位
        // 补码表示需要带符号扩展
        if (sign) {
        // 如果符号为负，尾数取反加 1（补码规则）
        mantissa = (~mantissa + 1) & 0x7FF; // 11 位补码
        return static_cast<int16_t>(mantissa | 0xF800); // 符号扩展
        } else {
        // 如果符号为正，直接返回尾数
        return static_cast<int16_t>(mantissa);
        }
    }
    int16_t extract_fp16_exponent(uint16_t fp16) {
        // 提取指数位（第 10 到 14 位）
        uint8_t exponent = (fp16 >> 10) & 0x1F;
        // 如果指数为 0，表示非规格化数，实际指数为 -14
        // 如果指数为 31，表示无穷大或 NaN，返回特殊值
        // 否则，实际指数 = 指数 - 15
        if (exponent == 0) {
            return -14; // 非规格化数
        } else if (exponent == 0x1F) {
            return 0x7FFF; // 无穷大或 NaN，返回最大值表示特殊值
            } else {
                return static_cast<int16_t>(exponent - 15); // 规格化数
                }
    }

    // 提取单精度浮点数的符号位和尾数，并转换为补码表示的32位有符号整数
    int32_t extract_mantissa(uint32_t float_bits) {
        // 提取符号位
        uint32_t sign_bit = (float_bits >> 31) & 0x1;

        // 提取尾数（包含隐藏位）
        uint32_t mantissa = (float_bits & 0x007FFFFF) | 0x00800000;

        // 组合符号位和尾数，低7位补0
        uint32_t result_bits = (sign_bit << 31) | (mantissa << 7);

        // 将结果转换为有符号整数（补码表示）
        int32_t result;
        std::memcpy(&result, &result_bits, sizeof(result));

        return result;
    }

    //求倒数平方根近似值
    double sqrcp(double x) {
    const float threehalfs = 1.5F;

    double xhalf = 0.5F * x;
    int i = *(int*)&x;  // 将浮点数的二进制表示转换为整数
    i = 0x5f3759df - (i >> 1);  // 魔法常数和位运算
    x = *(double*)&i;  // 将整数转换回浮点数
    x = x * (threehalfs - (xhalf * x * x));  // 牛顿迭代逼近

    return x;
}

};